package com.example.demomail.service;


import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.demomail.config.MailConfig;
import com.example.demomail.model.MailContentVo;
import com.example.demomail.model.RiskAlarmInfoVo;
import com.example.demomail.util.DateUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

/**
 * 邮件发件服务
 *
 * @author 邹敦宇
 * @date 2023/06/05
 */
@Service
@AllArgsConstructor
@Slf4j
public class MailSendService {

    private final MailConfig mailConfig;

    private Session getMailSession() {
        // 0.1 确定连接位置
        Properties properties = new Properties();
        // 设置smtp服务器的地址，
        properties.setProperty("mail.host", mailConfig.getHost());
//        properties.setProperty("mail.smtp.port", mailConfig.getPort());
        // 是否进行权限验证。
        properties.setProperty("mail.smtp.auth", String.valueOf(mailConfig.getSmtpAuth()));
        // 0.2确定权限（账号和密码）
        Authenticator authenticator = new Authenticator() {
            @Override
            public PasswordAuthentication getPasswordAuthentication() {
                // 填写邮箱的登录账户和授权密码
                return new PasswordAuthentication(mailConfig.getUsername(), mailConfig.getPassword());
            }
        };
        // 1 获得连接
        /**
         * properties：包含配置信息的对象，Properties类型 配置邮箱服务器地址、配置是否进行权限验证(帐号密码验证)等
         *
         * <p>authenticator：确定权限(帐号和密码)
         *
         * <p>所以就要在上面构建这两个对象。
         */
        Session session = Session.getDefaultInstance(properties, authenticator);
        return session;
    }


    /**
     * 数据服务-信息中心邮件模板
     *
     * @param riskAlarmInfoVo RiskAlarmInfoVo
     * @return 邮件文本
     */
    private String mailTextDataService2(RiskAlarmInfoVo riskAlarmInfoVo) {
        // 责任单位
        String company = riskAlarmInfoVo.getCompany();
        // 预警对象
        String entityName = riskAlarmInfoVo.getEntityName();

        // 预警类型
        String alarmType = riskAlarmInfoVo.getAlarmType();

        // 告警内容
        String alarmContent = riskAlarmInfoVo.getContent();

        // 邮件发送到处理时间间隔3天
        Date dealDate = DateUtil.calculateByDate(new Date(), 3);
        String dealDateStr = DateUtil.format(dealDate, "yyyy年MM月dd日");

        StringBuilder sb = new StringBuilder();
        sb.append("<span>").append(company).append("业务处：</span>")
                .append("<p>&emsp;&emsp;&emsp;&emsp;气象数盾-气象数据安全监管系统显示，贵单位").append(entityName).append(alarmType)
                .append("近一周").append(alarmContent)
                .append("。</p><p>&emsp;&emsp;&emsp;&emsp;为防止发生账户盗用等安全问题，请贵单位业务处尽快与账户使用人核实使用情况，确保访问数据均用于该账户申请时填报的使用用途。并请贵单位业务处于")
                .append(dealDateStr).append("前回复核实情况，逾期答复我们将冻结贵单位上述账户的使用权限。感谢配合！</p><p>&emsp;&emsp;&emsp;&emsp;具体情况如下：</p>")
                .append("<p>&emsp;&emsp;&emsp;&emsp;").append(entityName).append(alarmContent).append("。</p>");

        return sb.toString();

    }

    /**
     * 数据服务-外单位邮件模板（非信息中心）
     *
     * @param riskAlarmInfoVo RiskAlarmInfoVo
     * @return 邮件文本
     */
    private String mailTextDataService1(RiskAlarmInfoVo riskAlarmInfoVo) {
        // 预警对象
        String entityName = riskAlarmInfoVo.getEntityName();

        // 预警类型
        String alarmType = riskAlarmInfoVo.getAlarmType();

        // 告警内容
        String alarmContent = riskAlarmInfoVo.getContent();

        // 邮件发送到处理时间间隔3天
        Date dealDate = DateUtil.calculateByDate(new Date(), 3);
        String dealDateStr = DateUtil.format(dealDate, "yyyy年MM月dd日");

        StringBuilder sb = new StringBuilder();
        sb.append("<span>").append(entityName).append("业务处：</span>")
                .append("<p>&emsp;&emsp;&emsp;&emsp;气象数盾-气象数据安全监管系统显示，您近一周").append(alarmType)
                .append("。</p><p>&emsp;&emsp;&emsp;&emsp;为防止发生账户盗用等安全问题，请尽快核实使用情况，确保访问数据均用于该账户申请时填报的使用用途。并请贵单位业务处于")
                .append(dealDateStr).append("前回复核实情况，逾期答复我们将冻结贵单位上述账户的使用权限。感谢配合！</p><p>&emsp;&emsp;&emsp;&emsp;具体情况如下：</p>")
                .append("<p>&emsp;&emsp;&emsp;&emsp;").append(entityName).append(alarmContent).append("。</p>");

        return sb.toString();

    }


    /**
     * 回显邮件内容
     *
     * @param riskAlarmInfoVo RiskAlarmInfoVo
     * @return MailContentVo
     */
    public MailContentVo getMailContent(RiskAlarmInfoVo riskAlarmInfoVo) {
        MailContentVo mailContentVo = new MailContentVo();
        String mailText = "";
        String toAddress = "";
        List<String> copyAddressList = new ArrayList<>();

        String alarmLink = riskAlarmInfoVo.getAlarmLink();
        if ("数据服务".equals(alarmLink)) {
            if ("信息中心".equals(riskAlarmInfoVo.getCompany())) {
                mailText = mailTextDataService2(riskAlarmInfoVo);
                toAddress = "";
                copyAddressList = new ArrayList<>();
            } else {
                mailText = mailTextDataService1(riskAlarmInfoVo);
                toAddress = "";
                copyAddressList = new ArrayList<>();
            }
        } else {
            throw new RuntimeException("暂不支持此模块发送邮件");
        }
        mailContentVo.setMailText(mailText);
        mailContentVo.setToAddress(toAddress);
        mailContentVo.setCopyAddressList(copyAddressList);
        return mailContentVo;
    }

    /**
     * 发送邮件
     *
     * @param mailContentVo MailContentVo
     * @return 返回结果
     */
    public boolean sendMail(MailContentVo mailContentVo) {
        Session session = getMailSession();
        Message message = new MimeMessage(session);
        try {
            InternetAddress fromAddress = new InternetAddress(mailConfig.getUsername(), "气象数盾公共管理邮箱@cma.cn", "UTF-8");
            // From 表示发件人
            message.setFrom(fromAddress);
            InternetAddress toAddress = new InternetAddress(mailContentVo.getToAddress());
            // Recipient-TO 表示收件人，可以使单人，也可以是数组
            message.setRecipient(MimeMessage.RecipientType.TO, toAddress);
            List<String> copyList = mailContentVo.getCopyAddressList();
            if (!CollectionUtils.isEmpty(copyList)) {
                List<InternetAddress> internetAddressList = new ArrayList<>();
                for (String copyMail : copyList) {
                    InternetAddress copyAddress = new InternetAddress(copyMail);
                    internetAddressList.add(copyAddress);
                }
                InternetAddress[] internetAddresses = ArrayUtil.toArray(internetAddressList, InternetAddress.class);
                // Recipient-CC 表示抄送人
                message.setRecipients(Message.RecipientType.CC, internetAddresses);
            }
            // Subject 表示主题
            message.setSubject("气象数盾-气象数据安全预警");
            // Content 表示内容
            message.setContent(mailContentVo.getMailText(), "text/html;charset=UTF-8");
            Transport.send(message);
        } catch (MessagingException | UnsupportedEncodingException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    // 添加本地附件
    public String sendMailAndAttach(MailContentVo mailContentVo) {
        String resultMessage = "";
        Session session = getMailSession();
        Message message = new MimeMessage(session);
        try {
            InternetAddress fromAddress = new InternetAddress(mailConfig.getUsername(), "气象数盾公共管理邮箱@cma.cn", "UTF-8");
            // From 表示发件人
            message.setFrom(fromAddress);
            InternetAddress toAddress = new InternetAddress(mailContentVo.getToAddress());
            // Recipient-TO 表示收件人，可以使单人，也可以是数组
            message.setRecipient(MimeMessage.RecipientType.TO, toAddress);
            List<String> copyList = mailContentVo.getCopyAddressList();
            if (!CollectionUtils.isEmpty(copyList)) {
                List<InternetAddress> internetAddressList = new ArrayList<>();
                for (String copyMail : copyList) {
                    InternetAddress copyAddress = new InternetAddress(copyMail);
                    internetAddressList.add(copyAddress);
                }
                InternetAddress[] internetAddresses = ArrayUtil.toArray(internetAddressList, InternetAddress.class);
                // Recipient-CC 表示抄送人
                message.setRecipients(Message.RecipientType.CC, internetAddresses);
            }
            // Subject 表示主题
            message.setSubject("气象数盾-气象数据安全预警");
            message.setSentDate(new Date());

            MimeMultipart multipart = new MimeMultipart("mixed");
            message.setContent(multipart);

            MimeBodyPart htmlPart = new MimeBodyPart();
            htmlPart.setContent(mailContentVo.getMailText(), "text/html;charset=UTF-8");
            multipart.addBodyPart(htmlPart);

            MimeBodyPart attachPart = new MimeBodyPart();
            FileDataSource fileDataSource = new FileDataSource(new File("C:\\Users\\Administrator\\Documents\\sql-export\\cmadaas_dataflow_history.sql"));
            DataHandler dataHandler = new DataHandler(fileDataSource);
            attachPart.setDataHandler(dataHandler);
            attachPart.setFileName(MimeUtility.encodeText(dataHandler.getName()));
            multipart.addBodyPart(attachPart);

            message.saveChanges();
            Transport.send(message);
            log.info("发送成功");
            resultMessage = "邮件发送成功";
        } catch (AddressException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "请检查邮箱地址:" + e.getMessage();
        } catch (UnsupportedEncodingException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "转码异常，请查看详细信息" + e.getMessage();
        } catch (NoSuchProviderException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "邮件发送失败，详细错误原因：" + e.getMessage();
        } catch (MessagingException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "邮件发送失败，有可能的问题为服务器url不存在或附件不存在，具体请看详细信息：" + e.getMessage();
        }
        return resultMessage;
    }

    // 添加前端传递的附件
    public String sendMailAndAttachWeb(MultipartFile[] files, String mailContentVoStr) {
        String returnResult = "";
        MailContentVo mailContentVo = JSONObject.parseObject(mailContentVoStr, MailContentVo.class);
        if (mailContentVo == null) {
            returnResult = "参数解析错误";
        }


        String resultMessage = "";
        Session session = getMailSession();
        Message message = new MimeMessage(session);
        try {
            InternetAddress fromAddress = new InternetAddress(mailConfig.getUsername(), "气象数盾公共管理邮箱@cma.cn", "UTF-8");
            // From 表示发件人
            message.setFrom(fromAddress);
            InternetAddress toAddress = new InternetAddress(mailContentVo.getToAddress());
            // Recipient-TO 表示收件人，可以使单人，也可以是数组
            message.setRecipient(MimeMessage.RecipientType.TO, toAddress);
            List<String> copyList = mailContentVo.getCopyAddressList();
            if (!CollectionUtils.isEmpty(copyList)) {
                List<InternetAddress> internetAddressList = new ArrayList<>();
                for (String copyMail : copyList) {
                    InternetAddress copyAddress = new InternetAddress(copyMail);
                    internetAddressList.add(copyAddress);
                }
                InternetAddress[] internetAddresses = ArrayUtil.toArray(internetAddressList, InternetAddress.class);
                // Recipient-CC 表示抄送人
                message.setRecipients(Message.RecipientType.CC, internetAddresses);
            }
            // Subject 表示主题
            message.setSubject("气象数盾-气象数据安全预警");
            message.setSentDate(new Date());

            MimeMultipart multipart = new MimeMultipart("mixed");
            message.setContent(multipart);

            MimeBodyPart htmlPart = new MimeBodyPart();
            htmlPart.setContent(mailContentVo.getMailText(), "text/html;charset=UTF-8");
            multipart.addBodyPart(htmlPart);

            // 依次添加各个附件
            for (MultipartFile multipartFile : files) {
                MimeBodyPart mimeBodyPart = new MimeBodyPart();
                InputStream inputStream = multipartFile.getInputStream();
                ByteArrayDataSource byteArrayDataSource = new ByteArrayDataSource(inputStream, multipartFile.getContentType());
                mimeBodyPart.setDataHandler(new DataHandler(byteArrayDataSource));
                mimeBodyPart.setFileName(MimeUtility.encodeWord(multipartFile.getOriginalFilename(), "utf-8", "B"));
                multipart.addBodyPart(mimeBodyPart);
            }

            message.saveChanges();
            Transport.send(message);
            log.info("发送成功");
            resultMessage = "邮件发送成功";
        } catch (AddressException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "请检查邮箱地址:" + e.getMessage();
        } catch (UnsupportedEncodingException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "转码异常，请查看详细信息" + e.getMessage();
        } catch (NoSuchProviderException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "邮件发送失败，详细错误原因：" + e.getMessage();
        } catch (MessagingException e) {
            log.error("邮件发送失败，错误原因：" + e.getMessage());
            resultMessage = "邮件发送失败，有可能的问题为服务器url不存在或附件不存在，具体请看详细信息：" + e.getMessage();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return resultMessage;

    }
}
